use std::borrow::{Borrow, BorrowMut};
use std::collections::HashMap;
use std::env;
use std::fs::File;
use std::io;
use std::io::Read;
use std::thread;
use std::time::Duration;

fn main() {
    let args = env::args();
    for arg in args {
        println!("arg:{}", arg)
    }
    println!("Hello, world!");
    let b = Breakfast::winter("cooled boiled water"); //non pub fn
    let b1 = Breakfast::summer("cooled boiled water"); //pub fn
    println!("{:?}", b);
    println!("{:?}", b1);
    let p1 = someMode::Person::King {
        name: String::from("Blue"),
    };
    match p1 {
        someMode::Person::King { name } => {
            println!("{:?}", name);
        }
        _ => println!("{:?}", "None"),
    }

    b1.eat();
    b.eat();
    let path = "/Users/apple/study/rust/practices/structer/Cargo.lock";
    let f_str = read_text_from_file(&path);
    match f_str {
        Ok(s) => println!("file content#:{}", s),
        Err(e) => {
            match e.kind() {
                io::ErrorKind::NotFound => {
                    println!("file not found!")
                }
                _ => {
                    println!("can not read the file.");
                }
            };
        }
    };

    let ary = [1, 2, 8, 3, 4, 9];
    println!("max in ary:{}", max(&ary));
    // println!("max in ary:{}", max_ge(&ary));
    let mut p = Point { x: 1, y: 2 };
    let other_p = Point { x: 3, y: "abc" };
    println!("x in point:{}", p.x());
    println!("mix_up:{:?}", p.mix_up(other_p));
    // println!("f_str:{:?}", f_str);

    let p = Person {
        name: "xiaoming".into(),
        age: 18,
    };
    println!("{}", p.describe());
    output(p);
    output2(Person {
        name: "xiaoL".into(),
        age: 22,
    });
    let str1 = String::from("abc");
    let str2 = String::from("abcd");
    println!("longer str is:{}", longer(&str1, &str2));

    map_test();

    thread::spawn(spawn_thread);
    ///很显然随着主线程的结束，spawn 线程也随之结束了，并没有完成所有打印。
    for i in 0..3 {
        println!("main thread print {}", i);
        thread::sleep(Duration::from_millis(1));
    }
    closure_test();
    message_test();
    vec_test();
    panic!("panic error ...");
    println!("after panic error")
}
#[derive(Debug)]
struct Breakfast {
    pub toast: String,
    pub season_fruit: String,
}

impl Breakfast {
    ///结构体关联函数(没有&self)
    pub fn summer(toast: &str) -> Breakfast {
        Breakfast {
            toast: String::from(toast),
            season_fruit: String::from("watermelon"),
        }
    }
    fn winter(toast: &str) -> Breakfast {
        Breakfast {
            toast: String::from(toast),
            season_fruit: String::from("muskmelon"),
        }
    }
    ///结构体方法(有&self)
    pub fn eat(&self) {
        println!("toast:{},season_fruit:{}", self.toast, self.season_fruit);
    }
}

fn read_text_from_file(path: &str) -> Result<String, io::Error> {
    let mut f = File::open(path)?;
    let mut file_str = String::new();
    f.read_to_string(&mut file_str)?;
    Ok(file_str)
}

mod someMode {
    pub enum Person {
        King { name: String },
        Queen,
    }
}

fn max(ary: &[i32]) -> i32 {
    let mut index = 0;
    let mut max_index = 0;
    while index < ary.len() {
        if ary[index] > ary[max_index] {
            max_index = index
        }
        index += 1;
    }
    ary[max_index]
}
//
// fn max_ge<T:std::cmp::PartialOrd>(ary:&[T]) -> T{
//     let mut index=1;
//     let mut max_index=0;
//     while index<ary.len() {
//         if ary[index]>ary[max_index] {max_index=index }
//         index+=1;
//     }
//     ary[max_index]
// }
#[derive(Debug)]
struct Point<T, U> {
    x: T,
    y: U,
}
impl<T, U> Point<T, U> {
    pub fn x(&self) -> &T {
        &self.x
    }
    pub fn mix_up<V, W>(self, other: Point<V, W>) -> Point<T, W> {
        Point {
            x: self.x,
            y: other.y,
        }
    }
}

trait Descriptive {
    fn describe(&self) -> String {
        String::from("[Object]")
    }
}
struct Person {
    name: String,
    age: u8,
}
impl Descriptive for Person {
    fn describe(&self) -> String {
        format!("{},{}", self.name, self.age)
    }
}

fn output(desc: impl Descriptive) {
    println!("output the info :{}", desc.describe());
}

fn output2<T: Descriptive>(object: T) {
    println!("output2 the info:{}", object.describe());
}

fn longer<'a>(str1: &'a String, str2: &'a String) -> &'a String {
    if str1.len() > str2.len() {
        return str1;
    } else {
        return str2;
    }
}

fn vec_test() {
    let v = vec![1, 2, 3, 4, 5];
    println!(
        "v get 5: {}",
        match v.get(5) {
            Some(value) => value.to_string(),
            None => "None".to_string(),
        }
    );
    //thread 'main' panicked at 'index out of bounds: the len is 5 but the index is 5
    //如果用数组取值，必须确保不能越界 otherwise  panic !
    println!("as ary get value :{}", v[5])
}

fn map_test() {
    use std::collections::HashMap;
    let mut map: HashMap<&str, i32> = HashMap::new();
    // map.insert("aa",123);
    // map.insert("aa1",234);
    map_add_tuple(&mut map);
    for item in map.iter() {
        println!("{}:{}", item.0, item.1)
    }
}

fn map_add_tuple(map: &mut HashMap<&str, i32>) {
    map.insert("dd", 1231);
    map.insert("ee", 223);
    println!(
        "mut write and read in same scopy ?? dd = {}",
        map.get("dd").get_or_insert(&123)
    )
}

fn spawn_thread() {
    for i in vec![1, 2, 3, 4, 5] {
        println!("spawned thread print {}", i);
        thread::sleep(Duration::from_millis(10));
    }
}

fn closure_test() {
    let inc = |num: i32| -> i32 { num + 1 };
    println!("inc 1 :{}", inc(1))
}

fn message_test(){
    use std::thread;
    use std::sync::mpsc;
    let (sen,rev)=mpsc::channel();
    thread::spawn(move || {
        let v=String::from("hi");
        sen.send(v).unwrap();
    });
    let received=rev.recv().unwrap();
    println!("received:{}",received)
}